Skip to content

Align PostgreSQL Recipe outputs with secret ownership - #298

Open
willdavsmith wants to merge 3 commits into
mainfrom
willdavsmith-postgresql-recipe-secret-pattern
Open

Align PostgreSQL Recipe outputs with secret ownership#298
willdavsmith wants to merge 3 commits into
mainfrom
willdavsmith-postgresql-recipe-secret-pattern

Conversation

@willdavsmith

@willdavsmith willdavsmith commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Aligns the Kubernetes PostgreSQL Bicep and Terraform Recipes with the managed-secret ownership contract:

  • User-authored administrator credentials remain Recipe inputs and are not echoed through outputs.secrets.
  • Both Recipes return the schema-compatible string port value.
  • The test application authors a separate Radius.Security/secrets resource for the consuming container and binds its password through secretKeyRef.
  • The database connection is named postgresql, so the demo uses CONNECTION_POSTGRESQL_HOST, PORT, USERNAME, PASSWORD, and DATABASE and selects its PostgreSQL repository instead of silently falling back to the in-memory store.

Secret ownership

Radius.Data/postgreSqlDatabases receives username and the sensitive password from the application. Those user-supplied inputs configure the Recipe-owned Kubernetes Secret used by the PostgreSQL pod, but they are not generated outputs and must not be returned as managed Recipe secrets. This matches the Azure PostgreSQL Recipe, which returns only infrastructure outputs.

The preferred automatic input flow is to connect the container separately to the authored Radius.Security/secrets resource, which PR #300 projects as CONNECTION_<NAME>_<KEY> variables. This PR deliberately keeps the explicit secretKeyRef form because #300 is not merged and the shared PostgreSQL fixture is exercised independently by both Bicep and Terraform CI. The authored Radius Secret is named postgresql-client-credentials, distinct from the PostgreSQL Recipe's postgresql-credentials Kubernetes Secret, so both validation modes can deploy without collision. Coordinated downstream verification can switch the fixture to the automatic Secret connection once #300 and the corresponding Radius producer-managed reference support are available together.

Redis audit

No Redis files are changed. Redis accepts no credential input, so neither Kubernetes Recipe can echo a user-authored secret. Both Bicep and Terraform generate their connection URL from provisioned service outputs and emit the same url key through outputs.secrets; Azure Redis similarly emits its infrastructure-generated authenticated connection string. The schema declares secrets.name and secrets.url, and the test consumes url by reference. This matches the ownership contract and is not analogous to PostgreSQL's input-password violation.

Validation

  • Radius-bundled Bicep compiler: PostgreSQL Kubernetes Recipe
  • terraform fmt -check
  • terraform init -backend=false
  • terraform validate (passes with existing Kubernetes provider deprecation warnings)
  • git diff --check
  • DCO sign-offs and GPG signatures verified for all PR commits

Live Bicep and Terraform deployment validation is delegated to this PR's existing recipe CI because the local Recipe registry and Kubernetes cluster were unavailable.

The Kubernetes recipe returned `secrets: { password, connectionString }`, but
the postgreSqlDatabases type declares no `secrets` property, so neither value
was reachable from an application. The Azure recipe in
recipe-packs/azure/aks-recipepack.bicep maps only `host`, and deliberately does
not use the `outputs.secrets` mechanism it uses one entry away for redisCaches.

That distinction is intentional. PostgreSQL administrator credentials flow into
the recipe as user-supplied properties, so there is nothing to hand back; Redis
access keys are generated by the infrastructure and must flow out. Drop the
unreachable secrets output so both platforms agree, and document the reasoning.

Also emit `port` as a string to match `type: string` on the resource type, and
update test/app.bicep to show the supported pattern: the application authors its
own Radius.Security/secrets resource and binds it into the container with
valueFrom.secretKeyRef. A connection cannot carry the password (sensitive
properties redact to null and are skipped by the containers recipe), so this is
the only way to deliver it, and it keeps the value out of the pod spec and off
the container resource, where env values are stored unencrypted.

Signed-off-by: Will Smith <willdavsmith@gmail.com>
Signed-off-by: willdavsmith <willdavsmith@gmail.com>
Copilot AI lite review requested due to automatic review settings August 17, 2026 16:42
@willdavsmith
willdavsmith requested review from a team as code owners August 17, 2026 16:42
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Kubernetes postgreSqlDatabases recipe and its test application to align secret-handling behavior with the Azure implementation, ensuring credentials that flow into the recipe are not incorrectly emitted back as recipe secrets.

Changes:

  • Removed the Kubernetes recipe secrets output for postgreSqlDatabases and documented the rationale to prevent reintroducing it later.
  • Emitted port as a string in the recipe output to match the resource type schema.
  • Updated the test app to demonstrate developer-authored Radius.Security/secrets and binding the password into a consuming container via valueFrom.secretKeyRef.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
Data/postgreSqlDatabases/recipes/kubernetes/bicep/kubernetes-postgresql.bicep Removes unreachable secret outputs and aligns port output typing with the resource type schema.
Data/postgreSqlDatabases/test/app.bicep Demonstrates the supported pattern of authoring a secrets resource and binding the password into a container by reference.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +196 to +200
// and should author its own Radius.Security/secrets resource, binding it with
// `valueFrom.secretKeyRef` (see test/app.bicep). This matches the Azure recipe in
// recipe-packs/azure/aks-recipepack.bicep, which maps only `host`. Contrast with
// redisCaches, where the access key is generated by the infrastructure and so is
// returned via `outputs.secrets`.
The test application bound the password as POSTGRES_PASSWORD and named the
connection `postgres`, yielding CONNECTION_POSTGRES_* variables. The demo image
reads neither: samples/demo/src/db/repository.ts gates on
CONNECTION_POSTGRESQL_HOST and reads CONNECTION_POSTGRESQL_{PORT,USERNAME,
PASSWORD,DATABASE}. The container therefore never matched, silently fell back to
its in-memory store, and the test still passed because it only asserts that the
deployment succeeded.

Rename the connection to `postgresql` and bind the secret as
CONNECTION_POSTGRESQL_PASSWORD. That is the one variable Radius cannot supply
through the connection, because x-radius-sensitive properties redact to null on
reads and the containers recipe skips null values, so the binding fills the gap
rather than colliding with an injected variable.

Signed-off-by: Will Smith <willdavsmith@gmail.com>
Signed-off-by: willdavsmith <willdavsmith@gmail.com>
Signed-off-by: willdavsmith <willdavsmith@gmail.com>
@willdavsmith
willdavsmith force-pushed the willdavsmith-postgresql-recipe-secret-pattern branch from a56ad46 to 6ffec56 Compare August 20, 2026 21:57
@willdavsmith willdavsmith changed the title Align Kubernetes postgreSQL recipe secret handling with Azure Align PostgreSQL Recipe outputs with secret ownership Aug 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants